package utils;

import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;

/**
 * Estructura la información de una asociación.
 * 
 * @author emilio
 */
@SuppressWarnings("unused")
public class AssociationInfo {
	// TODO: utilizar el nombre de la asociación para algo.
	private String name;
	private Side side1;
	private Side side2;

	private AssociationInfo(Association as) {
		name = as.getName();
		side1 = new Side(as, 0);
		side2 = new Side(as, 1);
	}

	public static AssociationInfo getInfo(Association as) {
		return new AssociationInfo(as);
	}

	public Side getOppositeSide(org.eclipse.uml2.uml.Class fromClass) {
		if (side1.tt.equals(fromClass)) {
			return side2;
		} else {
			return side1;
		}
	}

	/**
	 * Estructura la información de uno de los lados de la asociación.
	 * 
	 * @author emilio
	 */
	public class Side {

		public Side(Association as, int side) {
			Type t = as.getEndTypes().get(side);
			tt = t;
			if (t instanceof Class) {
				type = ((Class) t).getName();
			} else if (t instanceof DataType) {
				type = ((DataType) t).getName();
			}
			Property p = as.getAllAttributes().get(side);
			role = p.getName();
			lower = p.getLower();
			upper = p.getUpper();
			if (upper < 0) {
				many = true;
			}
			navigable = p.isNavigable();
			composite = p.isComposite();
			_static = p.isStatic();
			ordered = p.isOrdered();
			unique = p.isUnique();
			readonly = p.isReadOnly();
		}

		/**
		 * El tipo de elemento del lado.
		 */
		private Type tt;
		/**
		 * Indica si el lado es "muchos"
		 */
		private boolean many;
		/**
		 * El nombre del tipo de elemento de uno de los lados (Clase, DataType)
		 */
		private String type;
		/**
		 * El nombre del rol de uno de los lados
		 */
		private String role;
		/**
		 * La cardinalidad mínima del lado
		 */
		// TODO: utilizar el valor lower de una relación para algo
		private int lower;
		/**
		 * La cardinalidad máximima del lado (-1 significa '*')
		 */
		private int upper;
		/**
		 * Indica si de ese lado hay navegabilidad.
		 */
		// TODO: utilizar el estado de 'navigable' de las relaciones para
		// algo.
		private boolean navigable;
		/**
		 * Indica si el lado es estático.
		 */
		// TODO: utilizar el estado de 'static' de las relaciones para algo.
		private boolean _static;
		/**
		 * Indica si el lado es único.
		 */
		// TODO: utilizar el estado de 'unique' de las relaciones para algo.
		private boolean unique;
		/**
		 * Indica si el lado es composición.
		 */
		// TODO: utilizar el estado de 'composite' de las relaciones para
		// algo.
		private boolean composite;
		/**
		 * Indica si el lado es ordenado.
		 */
		// TODO: utilizar el estado de 'ordered' de las relaciones para
		// algo.
		private boolean ordered;
		/**
		 * Indica si el lado es de solo lectura
		 */
		// TODO: utilizar el estado de 'readonly' de las relaciones para
		// algo.
		private boolean readonly;

		public Type getTt() {
			return tt;
		}

		public boolean isMany() {
			return many;
		}

		public String getType() {
			return type;
		}

		public String getRole() {
			return role;
		}

		public int getLower() {
			return lower;
		}

		public int getUpper() {
			return upper;
		}

		public boolean isNavigable() {
			return navigable;
		}

		public boolean is_static() {
			return _static;
		}

		public boolean isUnique() {
			return unique;
		}

		public boolean isComposite() {
			return composite;
		}

		public boolean isOrdered() {
			return ordered;
		}

		public boolean isReadonly() {
			return readonly;
		}
	}
}
